HDU 1026 广度优先搜索,BFS+路径的记录
哎~~花了半天的时间写了一个DFS的程序,结果无情的limit time exceed,然后到网上搜了一下,居然用的是BFS
一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(比如3步就必须达到条件)"的问题,它的空间效率高,但是找到的不一定是最优解,必须记录并完成整个搜索,故一般情况下,深搜需要非常高效的剪枝(优化).
像搜索最短路径这些的很明显要是用广搜,因为广搜的特性就是一层一层往下搜的,保证当前搜到的都是最优解,当然,最短路径只是一方面的应用,像什么最少状态转换也是可以应用的。
深搜就是优先搜索一棵子树,然后是另一棵,它和广搜相比,有着内存需要相对较少的优点,八皇后问题就是典型的应用,这类问题很明显是不能用广搜去解决的。或者像图论里面的找圈的算法,数的前序中序后序遍历等,都是深搜
深搜和广搜的不同之处是在于搜索顺序的不同。
深搜的实现类似于栈,每次选择栈顶元素去扩展,
广搜则是利用了队列,先被扩展的的节点优先拿去扩展。
搜索树的形态:深搜层数很多,广搜则是很宽。
深搜适合找出所有方案,广搜则用来找出最佳方案
深搜和广搜的区别:
深搜并不能保证第一次遇到目标点就是最短路径,因此要搜索所有可能的路径,因此要回溯,标记做了之后还要取消掉,因此同一个点可能被访问很多很多次。而广搜由于它的由近及远的结点扩展顺序,结点总是以最短路径被访问。一个结点如果第二次被访问,第二次的路径肯定不会比第一次的短,因此就没有必要再从这个结点向周围扩展――第一次访问这个结点的时候已经扩展过了,第二次再扩展只会得到更差的解。因此做过的标记不必去掉。因此同一个点至多只可能被访问一次。每访问一个结点,与它相连的边就被检查一次。因此最坏情况下,所有边都被检查一次,因此时间复杂度为O(E)。
BFS:
#include<stdio.h>
#include<ctype.h>
#include<queue>
#include<stack>
#include<limits.h>
#include<string.h>
#include<iostream>
using namespace std;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int n,m;
struct node
{
int time;
int x,y;
int prex,prey;
char data;
bool operator<(const node&a)const
{
return a.time<time;
}
}s[105][105];
typedef struct t
{
int x,y;
}T;
node cur1;T cur2,next2;
int BFS()
{
priority_queue<node>qu;
int i,x1,y1;
s[0][0].time=0;
qu.push(s[0][0]);
while(!qu.empty())
{
cur1=qu.top();
qu.pop();
if(cur1.x==n-1 && cur1.y==m-1)
return 1;
for(i=0;i<4;i++)
{
x1=cur1.x+dir[i][0];
y1=cur1.y+dir[i][1];
if(x1>=0 && x1<n && y1>=0 && y1<m)
{
if(s[x1][y1].data=='.'&& s[x1][y1].time>cur1.time+1)
{
s[x1][y1].time=cur1.time+1;
s[x1][y1].prex=cur1.x;
s[x1][y1].prey=cur1.y;
qu.push(s[x1][y1]);
}
else if(isdigit(s[x1][y1].data)&& s[x1][y1].time>cur1.time+s[x1][y1].data-'0')
{
s[x1][y1].time=cur1.time+s[x1][y1].data-'0'+1;
s[x1][y1].prex=cur1.x;
s[x1][y1].prey=cur1.y;
qu.push(s[x1][y1]);
}
}
}
}
return 0;
}
void printpath(int x,int y)
{
if(x==0&&y==0)return ;
int prex=s[x][y].prex;
int prey=s[x][y].prey;
printpath(prex,prey);
int prelength=s[prex][prey].time;
int length=s[x][y].time;
printf("%ds:(%d,%d)->(%d,%d)\n",prelength+1,prex,prey,x,y);
for(int i=prelength+2;i<=length;i++)
{
printf("%ds:FIGHT AT (%d,%d)\n",i,x,y);
}
}
int main()
{
setbuf(stdout,NULL);
int i,j;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cin>>s[i][j].data;
s[i][j].x=i;
s[i][j].y=j;
s[i][j].time=INT_MAX;
}
}
int state=BFS();
if(!state)
{
printf("God please help our poor hero.\n");
printf("FINISH\n");
continue;
}
printf("It takes %d seconds to reach the target position, let me show you the way.\n",s[n-1][m-1].time);
printpath(n-1,m-1);
printf("FINISH\n");
}
return 0;
}
顺便贴一下自己超时的DFS:
#include<iostream>
#include<stdio.h>
#include<limits.h>
#include<string.h>
#include<cstdlib>
using namespace std;
int N,M,OK;
char map[105][105];
int X[4]={1,-1,0,0};
int Y[4]={0,0,1,-1};
struct node
{
int prex;
int prey;
int length;
};
node visited[105][105];
void DFS(int x,int y,int prelength)
{
visited[x][y].length=prelength;
if(x==N-1&&y==M-1)
{
OK=1;
return ;
}
for(int i=0;i<4;i++)
{
int newx=x+X[i];
int newy=y+Y[i];
if(newx>=0&&newx<N&&newy>=0&&newy<M&&map[newx][newy]!='X')
{
if(map[newx][newy]=='.'&&(prelength+1<visited[newx][newy].length))
{
visited[newx][newy].prex=x;
visited[newx][newy].prey=y;
DFS(newx,newy,prelength+1);
}else
if(map[newx][newy]>'0'&& map[newx][newy]<='9')
{
int stay=map[newx][newy]-'0';
if(prelength+stay+1<visited[newx][newy].length)
{
visited[newx][newy].prex=x;
visited[newx][newy].prey=y;
DFS(newx,newy,prelength+stay+1);
}
}
}
}
}
void printpath(int x,int y)
{
if(x==0&&y==0)return ;
int prex=visited[x][y].prex;
int prey=visited[x][y].prey;
printpath(prex,prey);
int prelength=visited[prex][prey].length;
int length=visited[x][y].length;
printf("%ds:(%d,%d)->(%d,%d)\n",prelength+1,prex,prey,x,y);
for(int i=prelength+2;i<=length;i++)
{
printf("%ds:FIGHT AT (%d,%d)\n",i,x,y);
}
}
int main()
{
int i,j;
while(scanf("%d %d",&N,&M)!=EOF)
{
OK=0;
for(i=0;i<N;i++)
{
getchar();
for(j=0;j<M;j++)
{
//cin>>map[i][j]
scanf("%c",&map[i][j]);
visited[i][j].prex=-1;
visited[i][j].prey=-1;
visited[i][j].length=INT_MAX;
}
}
DFS(0,0,0);
if(!OK)
{
printf("God please help our poor hero.\n");
printf("FINISH\n");
continue;
}
printf("It takes %d seconds to reach the target position, let me show you the way.\n",visited[N-1][M-1].length);
printpath(N-1,M-1);
printf("FINISH\n");
}
return 0;
}
posted on 2011-07-29 10:09 lonelycatcher 阅读(4792) 评论(0) 编辑 收藏 举报